package com.borened.common.core.base.result;

import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.io.Serializable;

/**
 * 响应信息主体
 *
 * @author cch
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
@ApiModel("响应主体")
public class R<T> implements Serializable {
    /**
     * 成功
     */
    public static final ResultCode DEFAULT_SUCCESS = ResultCode.OK;
    /**
     * 默认失败响应码
     */
    public static final ResultCode DEFAULT_FAIL = ResultCode.SYSTEM_ERROR;
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("业务状态码")
    private int code;
    @ApiModelProperty("提示信息")
    private String msg;
    @ApiModelProperty("返回数据")
    private T data;

    /**
     * 针对需要返回操作结果类型的方法，根据操作结果选择性返回响应类型。
     *
     * @param status
     * @param <T>
     * @return
     */
    public static <T> R<T> judge(boolean isSuccess) {
        if (isSuccess) {
            return ok();
        } else {
            return fail(ResultCode.OPERATION_FAILED);
        }
    }

    public static <T> R<T> ok() {
        return ok(null, DEFAULT_SUCCESS);
    }

    public static <E> R<PageResult<E>> ok(PageResult<E> pageResult) {
        return ok(pageResult, DEFAULT_SUCCESS);
    }

    public static <T> R<T> ok(T data) {
        return ok(data, DEFAULT_SUCCESS);
    }

    public static <T> R<T> ok(T data, ResultCode resultCode) {
        return restResult(data, resultCode.getCode(), resultCode.getMsg());
    }

    public static <T> R<T> fail() {
        return fail(DEFAULT_FAIL);
    }

    public static <T> R<T> fail(String msg) {
        return fail(DEFAULT_FAIL, msg);
    }

    public static <T> R<T> fail(ResultCode resultCode, String msg) {
        return restResult(null, resultCode.getCode(), msg);
    }

    public static <T> R<T> fail(ResultCode resultCode) {
        return restResult(null, resultCode.getCode(), resultCode.getMsg());
    }


    private static <T> R<T> restResult(T data, int code, String msg) {
        R<T> apiResult = new R<>();
        apiResult.setCode(code);
        apiResult.setMsg(msg);
        apiResult.setData(data);
        return apiResult;
    }

    public static boolean isSuccess(R<?> result) {
        return result != null && DEFAULT_SUCCESS.getCode() == result.getCode();
    }

    /**
     * 包装已有响应结果
     * <p>
     * 针对远程调用的响应结果进行包装,一切校验错误应该在应用外层处理，不应该在远程服务内部调用时才响应错误；
     * </p>
     *
     * @param result
     * @param <T>
     * @return
     */
    public static <T> R<T> wrapResult(R<T> result) {
        //成功响应码直接返回
        if (R.isSuccess(result)) {
            return result;
        } else {
            //非成功响应码，转化为友好提示。
            return R.fail(ResultCode.SYSTEM_ERROR);
        }
    }
}
